const html5Tags = new Set([
    'a', 'abbr', 'address', 'area', 'article', 'aside', 'audio', 'b', 'base', 'bdi', 'bdo', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'cite', 'code', 'col', 'colgroup', 'data', 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div', 'dl', 'dt', 'em', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'link', 'main', 'map', 'mark', 'meta', 'meter', 'nav', 'noscript', 'object', 'ol', 'optgroup', 'option', 'output', 'p', 'param', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'script', 'section', 'select', 'small', 'source', 'span', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'title', 'tr', 'track', 'u', 'ul', 'var', 'video', 'wbr', 'template', 'main'
]);

/**
 * 是否为h5标签名
 * @param tagName
 * @return {boolean}
 */
export function isHtml5NativeTagName(tagName) {
    return html5Tags.has(tagName.toLowerCase());
}

/**
 * 监听元素尺寸变化
 * @param element
 * @param callback
 * @return {(function(): void)|*}
 */
export function observeElementSize(element, callback) {
  if (!element || typeof element !== 'object') {
    console.error('Invalid element provided');
    return;
  }

  const resizeObserver = new ResizeObserver(entries => {
    for (let entry of entries) {
      callback(entry.contentRect);
    }
  });

  resizeObserver.observe(element);

  // 返回一个函数以停止观察
  return () => {
    resizeObserver.disconnect();
  };
}

/**
 * 中横线命名转小驼峰命名
 * @param str
 * @return {string}
 */
export function kebabCaseToCamelCase(str) {
  // 使用中横线作为分隔符将字符串拆分为数组
  const parts = str.split('-');

  // 初始化驼峰字符串
  let camelCaseStr = '';

  // 遍历数组
  for (let i = 0; i < parts.length; i++) {
    // 获取当前部分
    const part = parts[i];

    // 如果是第一个部分，则直接添加
    if (i === 0) {
      camelCaseStr += part;
    } else {
      // 否则，将首字母转换为大写并添加
      camelCaseStr += part.charAt(0).toUpperCase() + part.slice(1);
    }
  }

  // 返回驼峰字符串
  return camelCaseStr;
}

/**
 * 中横线命名转大驼峰命名
 * @param str
 * @return {*}
 */
export function kebabCaseToPascalCase(str) {
  // 使用中横线作为分隔符将字符串拆分为数组
  const parts = str.split('-');

  // 将数组中的每个部分的首字母转换为大写
  const capitalizedParts = parts.map(part => part.charAt(0).toUpperCase() + part.slice(1));

  // 将数组元素拼接为大驼峰字符串
  const pascalCaseStr = capitalizedParts.join('');

  // 返回大驼峰字符串
  return pascalCaseStr;
}

/**
 * 小驼峰转中横线命名
 * @param str
 * @return {string}
 */
function camelCaseToKebabCase(str) {
  return str.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
}

/**
 * cssString转js对象
 * @param cssString
 * @return {{}}
 */
export function cssStringToVueStyleObject(cssString) {
  // 移除CSS字符串中的空格和换行
  const trimmedCssString = cssString.replace(/\s/g, '');

  // 以分号分割CSS声明
  const declarations = trimmedCssString.split(';');

  // 初始化一个空对象来保存样式
  const styleObject = {};

  // 遍历每个声明
  declarations.forEach(declaration => {
    // 如果声明不为空
    if (declaration) {
      // 以冒号分割键和值
      const [key, value] = declaration.split(':');

      // 确保键和值都是有效的
      if (key && value) {
        // 将键和值添加到styleObject中
        // Vue通常使用camelCase命名风格
        styleObject[kebabCaseToCamelCase(key)] = value.trim();
      }
    }
  });

  // 返回Vue可识别的CSS-JS对象
  return styleObject;
}

/**
 * js对象转cssString
 * @param vueStyleObject
 * @return {string}
 */
export function vueStyleObjectToCssString(vueStyleObject) {
  let cssString = '';

  for (let property in vueStyleObject) {
    if (vueStyleObject.hasOwnProperty(property)) {
      const cssProperty = camelCaseToKebabCase(property);
      const value = vueStyleObject[property];
      cssString += `  ${cssProperty}: ${value};\n`;
    }
  }

  return cssString;
}

/**
 * 去除换行与空格
 * @param str
 * @return {*}
 */
export function removeSpacesAndNewlines(str) {
  return str.replace(/[\s\n\r]+/g, '');
}
